home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / proc / procRpc.c < prev    next >
C/C++ Source or Header  |  1991-05-30  |  41KB  |  1,234 lines

  1. /*
  2.  * procRpc.c --
  3.  *
  4.  *    Procedures to handle remote procedure calls on behalf of migrated
  5.  *    processes, and for initial setup of migrated processes.
  6.  *
  7.  * Copyright (C) 1986, 1988 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/kernel/proc/RCS/procRpc.c,v 9.13 91/05/30 15:09:30 kupfer Exp $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #include <sprite.h>
  22. #include <stdlib.h>
  23. #include <proc.h>
  24. #include <procInt.h>
  25. #include <procMigrate.h>
  26. #include <mach.h>
  27. #include <fs.h>
  28. #include <migrate.h>
  29. #include <byte.h>
  30. #include <sig.h>
  31. #include <vm.h>
  32. #include <sys.h>
  33. #include <rpc.h>
  34. #include <timer.h>
  35. #include <sched.h>
  36. #include <sync.h>
  37. #include <sysSysCall.h>
  38. #include <sysSysCallParam.h>
  39. #include <devVid.h>
  40. #include <prof.h>
  41. #include <string.h>
  42. #include <stdio.h>
  43. #include <bstring.h>
  44.  
  45. /* 
  46.  * The PARANOIA code contains temporary checks to verify that 
  47.  * Proc_StringNCopy is being used correctly. -mdk 27-May-91.
  48.  */
  49. #define PARANOIA    1
  50. #if PARANOIA
  51. #define IsUserAddr(x)    ((x) >= mach_FirstUserAddr && (x) <= mach_LastUserAddr)
  52. Boolean procStringChecks = FALSE; /* do some paranoia checks on StringNCopy */
  53. #endif
  54.  
  55. static ReturnStatus     RpcProcExit _ARGS_((Proc_ControlBlock *procPtr, 
  56.                 Address dataPtr, int dataLength, 
  57.                 Address *replyDataPtr, 
  58.                 int *replyDataLengthPtr));
  59. static ReturnStatus     RpcProcFork _ARGS_((Proc_ControlBlock *parentProcPtr, 
  60.                 Address dataPtr, int dataLength, 
  61.                 Address *replyDataPtr, 
  62.                 int *replyDataLengthPtr));
  63. static ReturnStatus     RpcProcExec _ARGS_((Proc_ControlBlock *procPtr, 
  64.                 Address dataPtr, int dataLength, 
  65.                 Address *replyDataPtr, 
  66.                 int *replyDataLengthPtr));
  67. static ReturnStatus     RpcRemoteCall _ARGS_((Proc_RemoteCall *callPtr, 
  68.             Address dataPtr, int dataLength, 
  69.             Address *replyDataPtr, int *replyDataLengthPtr));
  70.  
  71. typedef ReturnStatus ((*PRS) ());
  72.  
  73. /*
  74.  * When a migrated system call is handled, a local procedure is called
  75.  * to perform the system call.  If the procedure has side effects,
  76.  * then before the results are returned, the process state on the
  77.  * remote node needs to be updated.  (This will be the case for
  78.  * routines such as Proc_SetIDs or Fs_Open.)  The "CallBack" type
  79.  * defines a structure containing pointers to two procedures.
  80.  *
  81.  * For each system call, there are several possibilities for procedures to
  82.  * be invoked:
  83.  *
  84.  *    1) The call should never be migrated (or has not been implemented).
  85.  *       This is a fatal error and is identified by localPtr being "RSNIL".
  86.  *    2) The call is a typical call that transfers data but has no side
  87.  *       effects.  localPtr is set, but sideEffectsPtr is RSNIL.
  88.  *    3) The call has side effects.  localPtr and sideEffectsPtr are non-NIL.
  89.  */
  90.  
  91. typedef struct {
  92.     PRS localPtr;        /* procedure to process call locally */
  93.     PRS sideEffectsPtr;        /* procedure to update info on remote node */
  94. } CallBack;
  95.  
  96. #define RSNIL ((PRS) NIL)
  97.  
  98. static CallBack callBackVector[] = {
  99. /*
  100.  *     callPtr      (why)        sideEffectsPtr    call number
  101.  */
  102.     { RpcProcFork,            RSNIL }, /* SYS_PROC_FORK       0 */
  103.     { RpcProcExec,            RSNIL }, /* SYS_PROC_EXEC       1 */
  104.     { RpcProcExit,            RSNIL }, /* SYS_PROC_EXIT       2 */
  105.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYNC_WAITTIME       3 */
  106.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_TEST_PRINTOUT       4 */
  107.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_TEST_GETLINE       5 */
  108.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_TEST_GETCHAR       6 */
  109.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_OPEN           7 */
  110.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_READ           8 */
  111.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_WRITE       9 */
  112.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_CLOSE      10 */
  113.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_REMOVE      11 */
  114.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_REMOVE_DIR      12 */
  115.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_MAKE_DIR      13 */
  116.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_CHANGE_DIR      14 */
  117.     { RSNIL /* Proc_Wait */,        RSNIL }, /* SYS_PROC_WAIT      15 */
  118.     { Proc_Detach,            RSNIL }, /* SYS_PROC_DETACH      16 */
  119.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETIDS      17 */
  120.     { Proc_SetIDs,            RSNIL }, /* SYS_PROC_SETIDS      18 */
  121.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETGROUPIDS  19 */
  122.     { RSNIL /* Proc_SetGroupIDs */,    RSNIL }, /* SYS_PROC_SETGROUPIDS  20 */
  123.     { Proc_GetFamilyID,            RSNIL }, /* SYS_PROC_GETFAMILYID  21 */
  124.     { Proc_SetFamilyID,            RSNIL }, /* SYS_PROC_SETFAMILYID  22 */
  125.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_TEST_RPC      23 */
  126.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_TEST_STATS      24 */
  127.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_VM_CREATEVA      25 */
  128.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_VM_DESTROYVA      26 */
  129.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SIG_SEND      27 */
  130.     { RSNIL /* Sig_Pause */,        RSNIL }, /* SYS_SIG_PAUSE      28 */
  131.     { RSNIL /* Sig_SetHoldMask */,    RSNIL }, /* SYS_SIG_SETHOLDMASK   29 */
  132.     { RSNIL /* Sig_SetAction */,    RSNIL }, /* SYS_SIG_SETACTION     30 */
  133.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROF_START      31 */
  134.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROF_END      32 */
  135.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROF_DUMP      33 */
  136.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_VM_CMD              34 */
  137.     { Sys_GetTimeOfDay,            RSNIL }, /* SYS_SYS_GETTIMEOFDAY  35 */
  138.     { Sys_SetTimeOfDay,            RSNIL }, /* SYS_SYS_SETTIMEOFDAY  36 */
  139.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYS_DONOTHING     37 */
  140.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETPCBINFO   38 */
  141.     { RSNIL /* Vm_GetSegInfo */,    RSNIL }, /* SYS_VM_GETSEGINFO     39 */
  142.     { Proc_GetResUsage,            RSNIL }, /* SYS_PROC_GETRESUSAGE  40 */
  143.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETPRIORITY  41 */
  144.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_SETPRIORITY  42 */
  145.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_DEBUG      43 */
  146.     { RSNIL /* Not implemented */,    RSNIL }, /* SYS_PROC_PROFILE      44 */
  147.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_FS_TRUNC      45 */
  148.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_FS_TRUNC_ID      46 */
  149.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_GET_NEW_ID      47 */
  150.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_GET_ATTRIBUTES 48 */
  151.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_GET_ATTR_ID      49 */
  152.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SET_ATTRIBUTES 50 */
  153.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SET_ATTR_ID      51 */
  154.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SET_DEF_PERM      52 */
  155.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_IO_CONTROL      53 */
  156.     { Dev_VidEnable,            RSNIL }, /* SYS_SYS_ENABLEDISPLAY 54 */
  157.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_PROC_SET_ENVIRON  55 */
  158.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_PROC_UNSET_ENVIRON 56 */
  159.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_PROC_GET_ENVIRON_VAR 57 */
  160.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_PROC_GET_ENVIRON_RANGE 58 */
  161.     { RSNIL /* obsolete */,          RSNIL }, /* SYS_PROC_INSTALL_ENVIRON 59 */
  162.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_PROC_COPY_ENVIRON 60 */
  163.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYNC_SLOWLOCK       61 */
  164.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYNC_SLOWWAIT     62 */
  165.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYNC_SLOWBROADCAST 63 */
  166.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_VM_PAGESIZE       64 */
  167.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_HARDLINK       65 */
  168.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_RENAME         66 */
  169.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SYMLINK        67 */
  170.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_READLINK       68 */
  171.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_CREATEPIPE     69 */
  172.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_VM_MAPKERNELINTOUSER 70 */
  173.     { Fs_AttachDiskStub,        RSNIL }, /* SYS_FS_ATTACH_DISK    71 */
  174.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SELECT         72 */
  175.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYS_SHUTDOWN      73 */
  176.     { Proc_Migrate,            RSNIL }, /* SYS_PROC_MIGRATE      74 */
  177.     { Fs_MakeDeviceStub,        RSNIL }, /* SYS_FS_MAKE_DEVICE    75 */
  178.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_COMMAND        76 */
  179.     { RSNIL /* obsolete */,        RSNIL }, /* SYS_FS_LOCK          77 */
  180.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_GETMACHINEINFO    78 */
  181.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_NET_INSTALL_ROUTE 79 */
  182.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_READVECTOR      80 */
  183.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_WRITEVECTOR      81 */
  184.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_CHECKACCESS    82 */
  185.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETINTERVALTIMER  83 */
  186.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_SETINTERVALTIMER  84 */
  187.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_WRITEBACKID    85 */
  188.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_EXEC_ENV     86 */
  189.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SET_ATTR_NEW   87 */
  190.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_FS_SET_ATTR_ID_NEW 88 */
  191.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_GETHOSTIDS   89 */
  192.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SCHED_IDLE_PROCESSOR 90 */
  193.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SCHED_START_PROCESSOR 91 */
  194.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_MACH_NUM_PROCESSORS 92 */
  195.     { RSNIL /* Not migrated */,         RSNIL }, /* SYS_PROF_PROFIL 93 */
  196.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_PROC_REMOTE_EXEC     94 */
  197.     { RSNIL /* Not migrated */,        RSNIL }, /* SYS_SYS_GETMACHINEINFO_NEW  95 */
  198.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MMAP 96 */
  199.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MUNMAP 97 */
  200.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MSYNC 98 */
  201.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MLOCK 99 */
  202.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MUNLOCK 100 */
  203.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MINCORE 101 */
  204.     { RSNIL /* Not migrated */,        RSNIL},  /* SYNC_SEMCTL 102 */
  205.     { RSNIL /* Not migrated */,        RSNIL},  /* SYNC_SEMGET 103 */
  206.     { RSNIL /* Not migrated */,        RSNIL},  /* SYNC_SEMOP 104 */
  207.     { RSNIL /* Not migrated */,        RSNIL},  /* VM_MPROTECT 105 */
  208. };
  209.  
  210.  
  211. /*
  212.  * Define an array of callbacks to do when handling migration commands.
  213.  * Each of these procedures is called with the following arguments:
  214.  *
  215.  *    func(cmdPtr, procPtr, inBufSize, inBufPtr, outBufSizePtr,
  216.  *          outBufPtrPtr)
  217.  *
  218.  * cmdPtr is a pointer to a ProcMigCommand structure containing the
  219.  * processID of the process on this host, and the input and output
  220.  * buffers are dependent on the command.  The output buffer arguments
  221.  * may be left alone, or set to point to a newly allocated buffer.
  222.  * procPtr is generally a pointer to a locked control block for the
  223.  * process being operated on, or is NIL in the case of
  224.  * ProcMigAcceptMigration creating a new process.
  225.  */
  226. static PRS commandCallbacks[] = {
  227.     ProcMigAcceptMigration,
  228.     ProcMigReceiveProcess,
  229.     ProcMigGetUpdate,
  230.     ProcMigEncapCallback,
  231.     ProcMigDestroyCmd,
  232.     ProcMigContinueProcess,
  233.     ProcMigGetSuspend,
  234. };
  235.  
  236.  
  237.  
  238.  
  239. /*
  240.  *----------------------------------------------------------------------
  241.  *
  242.  * RpcRemoteCall --
  243.  *
  244.  *    Service a system call for a migrated process.  Call the rpc
  245.  *    module to return the results, if any.
  246.  *
  247.  * Results:
  248.  *    Any data retured by the system call is passed back in a buffer,
  249.  *    as is its length.  The result returned by the system call is
  250.  *    returned as the ReturnStatus for this procedure.
  251.  *
  252.  * Side effects:
  253.  *    None.
  254.  *
  255.  *----------------------------------------------------------------------
  256.  */
  257.  
  258. /* ARGSUSED */
  259. static ReturnStatus
  260. RpcRemoteCall(callPtr, dataPtr, dataLength, replyDataPtr,
  261.            replyDataLengthPtr)
  262.     Proc_RemoteCall *callPtr;
  263.     Address dataPtr;
  264.     int dataLength;
  265.     Address *replyDataPtr;
  266.     int *replyDataLengthPtr;
  267. {
  268.     register Proc_ControlBlock *procPtr;
  269.     ReturnStatus status;
  270.     Sys_ArgArray args;
  271.     int disp;
  272.     int size;
  273.     int paddedSize;
  274.     Address inputPtr;
  275.     Address outputPtr;
  276.     int i;
  277.     Proc_TraceRecord record;
  278.  
  279.     if (proc_MigDebugLevel > 4) {
  280.     printf("Proc_RpcRemoteCall(%d) called.\n", callPtr->callNumber);
  281.     }
  282.  
  283.     *replyDataLengthPtr = 0;
  284.     *replyDataPtr = (Address) NIL;
  285.  
  286.     /*
  287.      * It's possible for an exit to come in while a process is in the NEW
  288.      * state if an error occurs while migrating it back home.  In this case,
  289.      * allow an exit to come in.  Otherwise, be more particular about which
  290.      * processIDs correspond to valid shadow processes.
  291.      */
  292.     procPtr = Proc_LockPID(callPtr->processID);
  293.     if (procPtr == (Proc_ControlBlock *) NIL
  294.     || ((procPtr->state != PROC_MIGRATED) &&
  295.         !((procPtr->state == PROC_NEW) &&
  296.           (callPtr->callNumber == SYS_PROC_EXIT)))) {
  297.     if ((procPtr != (Proc_ControlBlock *) NIL) &&
  298.         (procPtr->genFlags & PROC_MIGRATION_DONE)) {
  299.         /*
  300.          * Migration is complete, but it hasn't context switched yet.
  301.          * This is okay, since nothing it does after that point
  302.          * affects the process.  But, if the call is EXIT, flag an error.
  303.          * (There's still a race condition in the period between checking
  304.          * for this bit and context switching in the migration trap
  305.          * routine.  Hmm... Poll, maybe?)
  306.          */
  307.         if (callPtr->callNumber == SYS_PROC_EXIT) {
  308.         procPtr->genFlags |= PROC_MIG_ERROR;
  309.         Proc_Unlock(procPtr);
  310.         return(SUCCESS);
  311.         }
  312.     } else {
  313.         printf("Warning: Proc_RpcRemoteCall: invalid pid: %x.\n",
  314.            callPtr->processID);
  315.         if (procPtr != (Proc_ControlBlock *) NIL) {
  316.         printf("Proc_RpcRemoteCall: state = %d, call = %d.\n",
  317.                (int) procPtr->state, callPtr->callNumber);
  318.         Proc_Unlock(procPtr);
  319.         }
  320.         /*
  321.          * Return a special status that indicates the migrated process
  322.          * should be destroyed.
  323.          */
  324.         return (PROC_NO_PEER);
  325.     }
  326.     }
  327.     Proc_Unlock(procPtr);
  328.     if (callBackVector[callPtr->callNumber].localPtr ==
  329.         (ReturnStatus (*) ()) NIL) {
  330.      panic("Proc_RpcRemoteCall: can't handle call %d.\n",
  331.           callPtr->callNumber);
  332.     return(SYS_INVALID_SYSTEM_CALL);
  333.     }
  334.  
  335.     /*
  336.      * Set the effective process for this processor.
  337.      */
  338.  
  339.     Proc_SetEffectiveProc(procPtr);
  340.  
  341.     if (proc_DoTrace && proc_DoCallTrace) {
  342.     record.processID = callPtr->processID;
  343.     record.flags = PROC_MIGTRACE_START | PROC_MIGTRACE_HOME;
  344.     record.info.call.callNumber = callPtr->callNumber;
  345.     Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_CALL,
  346.              (ClientData) &record);
  347.     }
  348.  
  349.     if (!callPtr->parseArgs) {
  350.     status = (*(callBackVector[callPtr->callNumber].localPtr))
  351.         (procPtr, dataPtr, dataLength, replyDataPtr,
  352.          replyDataLengthPtr);
  353.     if (proc_MigDebugLevel > 4) {
  354.         printf("Proc_RpcRemoteCall: unparsed call %d returned %x.\n",
  355.                callPtr->callNumber, status);
  356.     }
  357.  
  358.     if (proc_DoTrace && proc_DoCallTrace) {
  359.         record.info.call.status = status;
  360.         record.flags &= ~PROC_MIGTRACE_START;
  361.         Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_CALL,
  362.              (ClientData) &record);
  363.     }
  364.     Proc_SetEffectiveProc((Proc_ControlBlock *) NIL);
  365.     return(status);
  366.     }
  367.  
  368.     *replyDataPtr = (Address) malloc(callPtr->replySize);
  369.     *replyDataLengthPtr = callPtr->replySize;
  370.     outputPtr = *replyDataPtr;
  371.     inputPtr = dataPtr;
  372.  
  373.     for (i = 0; i < callPtr->numArgs; i++) {
  374.     disp = callPtr->info[i].disposition;
  375.     size = callPtr->info[i].size;
  376.     paddedSize = Byte_AlignAddr(size);
  377.     if (disp & (SYS_PARAM_ACC | SYS_PARAM_COPY)) {
  378.         if (disp & SYS_PARAM_NIL) {
  379.         args.argArray[i] = USER_NIL;
  380.         } else if (disp & SYS_PARAM_OUT) {
  381.         if (disp & SYS_PARAM_IN) {
  382.             bcopy(inputPtr, outputPtr, size);
  383.             inputPtr += paddedSize;
  384.         }
  385.         args.argArray[i] = (int) outputPtr;
  386.         outputPtr += paddedSize;
  387.         } else {
  388.         args.argArray[i] = (int) inputPtr;
  389.         inputPtr += paddedSize;
  390.         }
  391.     } else {
  392.         if (size != sizeof(int)) {
  393.         panic("Proc_RpcRemoteCall: size mismatch.\n");
  394.         }
  395.         args.argArray[i] = * ((int *)inputPtr);
  396.         inputPtr += paddedSize;
  397.     }
  398.     }
  399.  
  400.     status = (*(callBackVector[callPtr->callNumber].localPtr)) (args);
  401.     if (proc_MigDebugLevel > 4) {
  402.      printf("Proc_RpcRemoteCall: parsed call %d returned %x.\n",
  403.            callPtr->callNumber, status);
  404.     }
  405.     Proc_SetEffectiveProc((Proc_ControlBlock *) NIL);
  406.  
  407.     if (proc_DoTrace && proc_DoCallTrace) {
  408.     record.info.call.status = status;
  409.     record.flags &= ~PROC_MIGTRACE_START;
  410.     Trace_Insert(proc_TraceHdrPtr, PROC_MIGTRACE_CALL,
  411.              (ClientData) &record);
  412.     }
  413.  
  414.     return(status);
  415. }
  416.  
  417.  
  418. /*
  419.  *----------------------------------------------------------------------
  420.  *
  421.  * RpcProcExit --
  422.  *
  423.  *    Perform an exit on the home node of a process.
  424.  *
  425.  * Results:
  426.  *    SUCCESS         - the process exited successfully.
  427.  *    PROC_INVALID_PID     - the process does not exist.
  428.  *
  429.  * Side effects:
  430.  *    None.
  431.  *
  432.  *----------------------------------------------------------------------
  433.  */
  434.  
  435. /* ARGSUSED */
  436. static ReturnStatus
  437. RpcProcExit(procPtr, dataPtr, dataLength, replyDataPtr,
  438.            replyDataLengthPtr)
  439.     register Proc_ControlBlock *procPtr;
  440.     Address dataPtr;
  441.     int dataLength;
  442.     Address *replyDataPtr;
  443.     int *replyDataLengthPtr;
  444. {
  445.     Timer_Ticks kernelTicks;
  446.     Timer_Ticks userTicks;
  447.     int count;
  448.     int reason;    /* Why the process is dying: EXITED, SIGNALED, DESTROYED  */
  449.     int    status;    /* Exit status or signal # or destroy status */
  450.     int code;    /* Signal sub-status */
  451.     Proc_PID pid;
  452.  
  453.     if (proc_MigDebugLevel > 4) {
  454.     printf("RpcProcExit called.\n");
  455.     }
  456.  
  457.     Proc_Lock(procPtr);
  458.     Byte_EmptyBuffer(dataPtr, Timer_Ticks,  kernelTicks);
  459.     Timer_AddTicks(procPtr->kernelCpuUsage.ticks, kernelTicks,
  460.            &procPtr->kernelCpuUsage.ticks);
  461.     Byte_EmptyBuffer(dataPtr, Timer_Ticks,  userTicks);
  462.     Timer_AddTicks(procPtr->userCpuUsage.ticks, userTicks,
  463.            &procPtr->userCpuUsage.ticks);
  464. #ifndef CLEAN
  465.     /*
  466.      * Record the remote usage for this process.  Note that the usage is
  467.      * also recorded in the total usage for this host under ProcExitProcess.
  468.      */
  469.     Timer_AddTicks(kernelTicks, userTicks, &userTicks);
  470.     ProcRecordUsage(userTicks, PROC_MIG_USAGE_REMOTE_CPU);
  471. #endif /* CLEAN */
  472.  
  473.     Byte_EmptyBuffer(dataPtr, int,  count);
  474.     procPtr->numQuantumEnds += count;
  475.     Byte_EmptyBuffer(dataPtr, int, count);
  476.     procPtr->numWaitEvents += count;
  477.  
  478.     Byte_EmptyBuffer(dataPtr, int, reason);
  479.     Byte_EmptyBuffer(dataPtr, int, status);
  480.     Byte_EmptyBuffer(dataPtr, int, code);
  481.  
  482.  
  483.     pid = procPtr->processID;
  484.  
  485.     /*
  486.      * Perform an exit on behalf of the process.  The process is
  487.      * unlocked as a side effect.
  488.      */
  489.     ProcExitProcess(procPtr, reason, status, code, FALSE);
  490.  
  491.     /*
  492.      * Remove the dependency on the other host.
  493.      */
  494.     ProcMigRemoveDependency(pid, TRUE);
  495.  
  496.     /*
  497.      * Update statistics.
  498.      */
  499. #ifndef CLEAN
  500.     if (proc_MigDoStats) {
  501.     PROC_MIG_DEC_STAT(remote);
  502.     }
  503. #endif /* CLEAN */   
  504.  
  505.     if (proc_MigDebugLevel > 4) {
  506.     printf("RpcProcExit returning SUCCESS.\n");
  507.     }
  508.     return(SUCCESS);
  509. }
  510.  
  511.  
  512. /*
  513.  *----------------------------------------------------------------------
  514.  *
  515.  * RpcProcExec --
  516.  *
  517.  *    Perform an exec on the home node of a process.
  518.  *
  519.  * Results:
  520.  *    SUCCESS         - The process is migrated and has been
  521.  *                   modified.
  522.  *
  523.  * Side effects:
  524.  *    the process's argument string and effective userID are modified.
  525.  *
  526.  *----------------------------------------------------------------------
  527.  */
  528.  
  529. /* ARGSUSED */
  530. static ReturnStatus
  531. RpcProcExec(procPtr, dataPtr, dataLength, replyDataPtr,
  532.            replyDataLengthPtr)
  533.     register Proc_ControlBlock *procPtr;
  534.     Address dataPtr;
  535.     int dataLength;
  536.     Address *replyDataPtr;
  537.     int *replyDataLengthPtr;
  538. {
  539.     int uid;
  540.     char *argString;
  541.  
  542.     if (proc_MigDebugLevel > 4) {
  543.     printf("RpcProcExec called.\n");
  544.     }
  545.  
  546.     Proc_Lock(procPtr);
  547.     Byte_EmptyBuffer(dataPtr, int, uid);
  548.     if (uid != -1) {
  549.     procPtr->effectiveUserID = uid;
  550.     }
  551.     /*
  552.      * The data area contains the uid followed by the argString. Therefore,
  553.      * we allocate space equal to the data length - 1.  (The null terminator
  554.      * is included in the string passed over).
  555.      */
  556.     argString = malloc(dataLength - 1);
  557.     if (procPtr->argString != (char *) NIL) {
  558.     free(procPtr->argString);
  559.     }
  560.     procPtr->argString = argString;
  561.     (void) strcpy(argString, dataPtr);
  562.  
  563.     if (proc_MigDebugLevel > 6) {
  564.     printf("RpcProcExec setting argString to '%s'.\n", argString);
  565.     }
  566.  
  567.  
  568.     Proc_Unlock(procPtr);
  569.  
  570.     if (proc_MigDebugLevel > 4) {
  571.     printf("RpcProcExec returning SUCCESS.\n");
  572.     }
  573.     return(SUCCESS);
  574. }
  575.  
  576.  
  577. /*
  578.  *----------------------------------------------------------------------
  579.  *
  580.  * RpcProcFork --
  581.  *
  582.  *    Perform a fork on the home node of a process.  This involves allocating
  583.  *    a PCB and process ID for the process, and copying certain local
  584.  *    information such as the environment.
  585.  *
  586.  * Results:
  587.  *    SUCCESS         - the process forked successfully.
  588.  *    PROC_INVALID_PID     - the process does not exist.
  589.  *
  590.  * Side effects:
  591.  *    A new process is created.  The identifier of the newly-created
  592.  *    process is returned to the remote node in the data buffer.
  593.  *
  594.  *----------------------------------------------------------------------
  595.  */
  596.  
  597. /* ARGSUSED */
  598. static ReturnStatus
  599. RpcProcFork(parentProcPtr, dataPtr, dataLength, replyDataPtr,
  600.         replyDataLengthPtr)
  601.     register Proc_ControlBlock *parentProcPtr;
  602.     Address dataPtr;
  603.     int dataLength;
  604.     Address *replyDataPtr;
  605.     int *replyDataLengthPtr;
  606. {
  607.     Proc_ControlBlock     *childProcPtr;    /* The new process being created */
  608.  
  609.     if (proc_MigDebugLevel > 3) {
  610.     printf("RpcProcFork called.\n");
  611.     }
  612.     childProcPtr = ProcGetUnusedPCB();
  613.  
  614.     childProcPtr->Prof_Scale = 0;
  615.     Prof_Enable(childProcPtr, parentProcPtr->Prof_Buffer, 
  616.         parentProcPtr->Prof_BufferSize, parentProcPtr->Prof_Offset,
  617.     parentProcPtr->Prof_Scale);
  618.  
  619.     childProcPtr->state         = PROC_MIGRATED;
  620.     childProcPtr->genFlags         = PROC_USER | PROC_NO_VM;
  621.     childProcPtr->syncFlags        = 0;
  622.     childProcPtr->schedFlags        = 0;
  623.     childProcPtr->exitFlags        = 0;
  624.  
  625.     childProcPtr->billingRate     = parentProcPtr->billingRate;
  626.     childProcPtr->recentUsage     = 0;
  627.     childProcPtr->weightedUsage     = 0;
  628.     childProcPtr->unweightedUsage     = 0;
  629.  
  630.     childProcPtr->kernelCpuUsage.ticks     = timer_TicksZeroSeconds;
  631.     childProcPtr->userCpuUsage.ticks         = timer_TicksZeroSeconds;
  632.     childProcPtr->childKernelCpuUsage.ticks     = timer_TicksZeroSeconds;
  633.     childProcPtr->childUserCpuUsage.ticks     = timer_TicksZeroSeconds;
  634.     childProcPtr->numQuantumEnds    = 0;
  635.     childProcPtr->numWaitEvents    = 0;
  636.  
  637.     childProcPtr->parentID         = parentProcPtr->processID;
  638.     childProcPtr->userID         = parentProcPtr->userID;
  639.     childProcPtr->effectiveUserID     = parentProcPtr->effectiveUserID;
  640.     childProcPtr->familyID         = parentProcPtr->familyID;
  641.  
  642.     if (childProcPtr->argString != (char *) NIL) {
  643.     free(childProcPtr->argString);
  644.     }
  645.     if (parentProcPtr->argString != (Address) NIL) {
  646.     childProcPtr->argString =
  647.         (char *) malloc(strlen(parentProcPtr->argString) + 1);
  648.     (void) strcpy(childProcPtr->argString, parentProcPtr->argString);
  649.     } else {
  650.     childProcPtr->argString    = (char *) NIL;
  651.     }
  652.  
  653.  
  654.     Vm_ProcInit(childProcPtr);
  655.  
  656.     if (ProcFamilyInsert(childProcPtr, childProcPtr->familyID) != SUCCESS) {
  657.     panic("RpcProcFork: ProcFamilyInsert failed\n");
  658.     }
  659.  
  660.     /*
  661.      *  Initialize our child list to remove any old links.
  662.      *  Insert this PCB entry into the list of children of our parent.
  663.      */
  664.     List_Init((List_Links *) childProcPtr->childList);
  665.     List_Insert((List_Links *) &(childProcPtr->siblingElement),
  666.         LIST_ATREAR(parentProcPtr->childList));
  667.  
  668.     Sig_Fork(parentProcPtr, childProcPtr);
  669.  
  670.     /*
  671.      * Initialize information for migration.
  672.      */
  673.  
  674.     Byte_EmptyBuffer(dataPtr, Proc_PID, childProcPtr->peerProcessID);
  675.     childProcPtr->peerHostID = parentProcPtr->peerHostID;
  676.  
  677.     /*
  678.      * Set up the environment of the process.
  679.      */
  680.  
  681.      ProcSetupEnviron(childProcPtr);
  682.  
  683.     /*
  684.      * Have the new process inherit filesystem state.
  685.      */
  686.     Fs_InheritState(parentProcPtr, childProcPtr);
  687.  
  688.     /*
  689.      * Note the dependency of the new process on the other host.
  690.      */
  691.     ProcMigAddDependency(childProcPtr->processID, childProcPtr->peerProcessID);
  692.  
  693.     /*
  694.      * Update statistics.
  695.      */
  696. #ifndef CLEAN
  697.     if (proc_MigDoStats) {
  698.     PROC_MIG_INC_STAT(remote);
  699.     }
  700. #endif /* CLEAN */   
  701.  
  702.     /*
  703.      * Send back the child's process ID in the replyData buffer.
  704.      */
  705.  
  706.     *replyDataLengthPtr = sizeof(Proc_PID);
  707.     *replyDataPtr = (Address) malloc(sizeof(Proc_PID));
  708.     * ((Proc_PID *) *replyDataPtr) = childProcPtr->processID;
  709.  
  710.     if (proc_MigDebugLevel > 3) {
  711.     printf("RpcProcFork returning SUCCESS.\n");
  712.     }
  713.     return(SUCCESS);
  714. }
  715.  
  716.  
  717. /*
  718.  *----------------------------------------------------------------------
  719.  *
  720.  * Proc_ByteCopy --
  721.  *
  722.  *    Perform a copy into or out of the user's address space.  If
  723.  *    the user process is migrated, copy the arguments directly and
  724.  *    let the rpc server send the results to the remote node.
  725.  *
  726.  * Results:
  727.  *    SUCCESS         - the copy was performed successfully.
  728.  *    SYS_ARG_NOACCESS     - the argument was not accessible.
  729.  *
  730.  * Side effects:
  731.  *    None.
  732.  *
  733.  *----------------------------------------------------------------------
  734.  */
  735.  
  736. ReturnStatus
  737. Proc_ByteCopy(copyIn, numBytes, sourcePtr, destPtr)
  738.     Boolean copyIn;        /* copy into or out of kernel address space */
  739.     int numBytes;        /* The number of bytes to copy */
  740.     Address sourcePtr;        /* Where to copy from */
  741.     Address destPtr;        /* Where to copy to */
  742. {
  743.     ReturnStatus status = SUCCESS;
  744.  
  745.     if (Proc_UseRpcBuffer()) {
  746.     bcopy(sourcePtr, destPtr, numBytes);
  747.     } else if (copyIn) {
  748.     status = Vm_CopyIn(numBytes, sourcePtr, destPtr);
  749.     } else {
  750.     status = Vm_CopyOut(numBytes, sourcePtr, destPtr);
  751.     }
  752.     return(status);
  753. }
  754.  
  755.  
  756. /*
  757.  *----------------------------------------------------------------------
  758.  *
  759.  * Proc_StringNCopy --
  760.  *
  761.  *    Copy a string from the user's address space to a buffer of 
  762.  *    limited length.  If the user process is a ghost (an RPC that 
  763.  *    was migrated home), copy the argument directly.  cf. 
  764.  *    Proc_ByteCopy and Vm_StringNCopy.
  765.  *
  766.  * Results:
  767.  *    SUCCESS
  768.  *
  769.  * Side effects:
  770.  *    *strNameLength is set to the actual length of the string copied.
  771.  *
  772.  *----------------------------------------------------------------------
  773.  */
  774.  
  775. ReturnStatus
  776. Proc_StringNCopy(numBytes, srcStr, destStr, strLengthPtr)
  777.     register int    numBytes;    /* Maximum number of bytes to copy. */
  778.     register char    *srcStr;    /* String to copy. */
  779.     register char    *destStr;    /* Where to copy string to. */
  780.     int            *strLengthPtr;    /* Where to return actual length of
  781.                      * string copied. */
  782. {
  783.     register int length;
  784.     ReturnStatus status;
  785.  
  786. #if PARANOIA
  787.     if (procStringChecks && !IsUserAddr(srcStr)) {
  788.     panic("Proc_StringNCopy: copying from kernel\n");
  789.     }
  790.     if (procStringChecks && IsUserAddr(destStr)) {
  791.     panic("Proc_StringNCopy: copying to user\n");
  792.     }
  793. #endif
  794.  
  795.     if (!Proc_UseRpcBuffer()) {
  796.     status =  Vm_StringNCopy(numBytes, srcStr, destStr,
  797.                  strLengthPtr);
  798.     } else {
  799.     for (length = 0; (length < numBytes) && (*srcStr != '\0'); length++) {
  800.         *destStr++ = *srcStr++;
  801.     }
  802.     *destStr = '\0';
  803.     *strLengthPtr = length;
  804.     status = SUCCESS;
  805.     }
  806.  
  807.     return status;
  808. }
  809.  
  810.  
  811.  
  812. /*
  813.  *----------------------------------------------------------------------
  814.  *
  815.  * Proc_MakeStringAccessible --
  816.  *
  817.  *    If the string is in user space, convert the user space path pointer
  818.  *    into a kernel valid pointer.  If the string is in kernel space
  819.  *    already (i.e., a system call is being performed on behalf of a
  820.  *    migrated process), do nothing.
  821.  *
  822.  *
  823.  * Results:
  824.  *    SYS_ARG_NOACCESS    - the Vm_MakeAccessible call failed.
  825.  *    PROC_INVALID_STRING - the length of the string exceeds the maximum
  826.  *                          permissible length or is not null-terminated.
  827.  *
  828.  *    The new pointer is returned in *stringPtrPtr.  The length of the
  829.  *    string is returned in *newLengthPtr if newLengthPtr is non-NIL.
  830.  *
  831.  * Side effects:
  832.  *    Make an area of the user code accessible.
  833.  *
  834.  *----------------------------------------------------------------------
  835.  */
  836. ReturnStatus
  837. Proc_MakeStringAccessible(maxLength, stringPtrPtr, accessLengthPtr,
  838.               newLengthPtr)
  839.     int maxLength;     /* Maximum allowable string length */
  840.     char **stringPtrPtr; /* On input *stringPtrPtr is a user space pointer,
  841.               * On output *stringPtrPtr is a kernel space pointer */
  842.     int *accessLengthPtr;/* Number of bytes actually made accessible. */
  843.     int *newLengthPtr;     /* length of the string that is made accessible */
  844. {
  845.     int accessLength = maxLength;
  846.     register int realLength;
  847.     Boolean madeAccessible = FALSE;
  848.     register char *charPtr;
  849.  
  850.     if (!Proc_UseRpcBuffer()) {
  851.     Vm_MakeAccessible(VM_READONLY_ACCESS,
  852.               maxLength, (Address) *stringPtrPtr,
  853.               &accessLength, (Address *) stringPtrPtr);
  854.     if (*stringPtrPtr == (Address)NIL) {
  855.         return(SYS_ARG_NOACCESS);
  856.     }
  857.     madeAccessible = TRUE;
  858.     *accessLengthPtr = accessLength;
  859.     }
  860.     /*
  861.      * Do a length check.  If the file name takes up all the addressable
  862.      * space then it isn't null terminated and will cause problems later.
  863.      */
  864.     for (charPtr = *stringPtrPtr, realLength = 0;
  865.      (realLength < accessLength) && (*charPtr != '\0');
  866.      charPtr++, realLength++) {
  867.      }
  868.     if (realLength == accessLength && *charPtr != '\0') {
  869.     if (madeAccessible) {
  870.         Vm_MakeUnaccessible((Address) *stringPtrPtr, accessLength);
  871.     }
  872.     *stringPtrPtr = (Address)NIL;
  873.     return(PROC_INVALID_STRING);
  874.     }
  875.     if (newLengthPtr != (int *) NIL) {
  876.     *newLengthPtr = realLength;
  877.     }
  878.     return(SUCCESS);
  879. }
  880.  
  881.  
  882. /*
  883.  *----------------------------------------------------------------------
  884.  *
  885.  * Proc_MakeUnaccessible
  886.  *
  887.  *    If the pointer is to something that was made accessible as a
  888.  *    result of a local system call, call Vm_MakeUnaccessible.  
  889.  *    Otherwise, the pointer is to a (kernel) RPC buffer and should 
  890.  *    be left alone.  This routine is used by generic system call
  891.  *    stubs that may be called either locally or on behalf of a
  892.  *    ghost process.
  893.  *
  894.  * Results:
  895.  *    None.
  896.  *
  897.  * Side effects:
  898.  *    Kernel page table may be modified.
  899.  *
  900.  *----------------------------------------------------------------------
  901.  */
  902. void
  903. Proc_MakeUnaccessible(addr, numBytes)
  904.     Address        addr;
  905.     int            numBytes;
  906. {
  907.  
  908.     if (!Proc_UseRpcBuffer()) {
  909.     Vm_MakeUnaccessible(addr, numBytes);
  910.     }
  911. }
  912.  
  913.  
  914. /*
  915.  *----------------------------------------------------------------------
  916.  *
  917.  * Proc_RpcRemoteWait --
  918.  *
  919.  *    Perform a Proc_Wait on behalf of a migrated process.
  920.  *
  921.  * Results:
  922.  *    SUCCESS - an exiting/detached child was found and the information
  923.  *          about it is being returned.
  924.  *    PROC_NO_EXITS - No children have performed an exit or detach
  925.  *                (except possibly children about whom the parent has
  926.  *            already been notified).
  927.  *
  928.  * Side effects:
  929.  *    If the process has no exiting children and it has specified that
  930.  *    it should block until a child exits, the process is established
  931.  *    as performing a remote wait.
  932.  *
  933.  *----------------------------------------------------------------------
  934.  */
  935.  
  936. /* ARGSUSED */
  937. ReturnStatus
  938. Proc_RpcRemoteWait(srvToken, clientID, command, storagePtr)
  939.     ClientData srvToken;    /* Handle on server process passed to
  940.                  * Rpc_Reply */
  941.     int clientID;        /* Sprite ID of client host */
  942.     int command;        /* Command identifier */
  943.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  944.                  * buffers and also indicate the exact amount
  945.                  * of data in the request buffers.  The reply
  946.                  * fields are initialized to NIL for the
  947.                  * pointers and 0 for the lengths.  This can
  948.                  * be passed to Rpc_Reply */
  949. {
  950.     ReturnStatus status;
  951.     ProcChildInfo *childInfoPtr;
  952.     register ProcRemoteWaitCmd *cmdPtr;
  953.     Proc_PID *pidArray;
  954.     Rpc_ReplyMem *replyMemPtr;
  955.     Proc_ControlBlock *procPtr;
  956.  
  957.     if (proc_MigDebugLevel > 3) {
  958.     printf("Proc_RpcRemoteWait entered.\n");
  959.  
  960.     }
  961.  
  962.     cmdPtr = (ProcRemoteWaitCmd *) storagePtr->requestParamPtr;
  963.     procPtr = Proc_LockPID(cmdPtr->pid);
  964.     if (procPtr == (Proc_ControlBlock *) NIL) {
  965.     return (PROC_NO_PEER);
  966.     } else if (procPtr->state != PROC_MIGRATED ||
  967.         procPtr->peerHostID != clientID) {
  968.     Proc_Unlock(procPtr);
  969.     return (PROC_NO_PEER);
  970.     }
  971.     pidArray = (Proc_PID *) storagePtr->requestDataPtr;
  972.     childInfoPtr = (ProcChildInfo *) malloc(sizeof(ProcChildInfo));
  973.  
  974.     status = ProcServiceRemoteWait(procPtr, cmdPtr->flags, cmdPtr->numPids,
  975.                     pidArray, cmdPtr->token,
  976.                    childInfoPtr);
  977.  
  978.     Proc_Unlock(procPtr);
  979.     if (status == SUCCESS) {
  980.     storagePtr->replyDataPtr = (Address) childInfoPtr;
  981.     storagePtr->replyDataSize = sizeof(ProcChildInfo);
  982.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  983.     replyMemPtr->paramPtr = (Address) NIL;
  984.     replyMemPtr->dataPtr = storagePtr->replyDataPtr;
  985.  
  986.     Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  987.         (ClientData) replyMemPtr);
  988.     } else {
  989.     free((Address) childInfoPtr);
  990.     }
  991.  
  992.     if (proc_MigDebugLevel > 3) {
  993.     printf("Proc_RpcRemoteWait: returning %x.\n", status);
  994.     }
  995.     return(status);
  996. }
  997.  
  998.  
  999.  
  1000. /*
  1001.  *----------------------------------------------------------------------
  1002.  *
  1003.  * Proc_RpcMigCommand --
  1004.  *
  1005.  *    Handle a request regarding process migration.  This may be a
  1006.  *    request to initiate migration, a buffer containing part or all
  1007.  *    of the encapsulated state of a process, a callback by another
  1008.  *    module during state transfer, or a command to asynchronously
  1009.  *    kill a migrated process due to some error.
  1010.  *
  1011.  * Results:
  1012.  *    SUCCESS is returned to the rpc daemon invoking this procedure.
  1013.  *    Various ReturnStatus values may be returned via the RPC itself.
  1014.  *    It is either SUCCESS or some error returned by a lower level routine
  1015.  *    (e.g., no such process). In addition, the called routine may
  1016.  *    return arbitrary data.
  1017.  *
  1018.  * Side effects:
  1019.  *    Variable (see above).
  1020.  *
  1021.  *----------------------------------------------------------------------
  1022.  */
  1023. /*ARGSUSED*/
  1024. ReturnStatus
  1025. Proc_RpcMigCommand(srvToken, hostID, command, storagePtr)
  1026.     ClientData srvToken;    /* Handle on server process passed to
  1027.                  * Rpc_Reply */
  1028.     int hostID;            /* Sprite ID of host invoking RPC */
  1029.     int command;        /* Command identifier */
  1030.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  1031.                  * buffers and also indicate the exact amount
  1032.                  * of data in the request buffers.  The reply
  1033.                  * fields are initialized to NIL for the
  1034.                  * pointers and 0 for the lengths.  This can
  1035.                  * be passed to Rpc_Reply */
  1036. {
  1037.     ReturnStatus status;
  1038.     Rpc_ReplyMem    *replyMemPtr;
  1039.     ProcMigCmd *commandPtr =
  1040.     (ProcMigCmd *) storagePtr->requestParamPtr;
  1041.     Proc_MigBuffer    inBuf;
  1042.     Proc_MigBuffer    outBuf;
  1043.     Proc_ControlBlock *procPtr;
  1044.     int requestSize;
  1045.  
  1046.     if (proc_MigDebugLevel > 5) {
  1047.     printf("Proc_RpcMigCommand: called from host %d with command %d commandPtr %x.\n",
  1048.            hostID, command, (int) commandPtr);
  1049.     }
  1050.     if (storagePtr->requestParamSize != sizeof(ProcMigCmd)) {
  1051.     if (proc_MigDebugLevel > 0) {
  1052.         printf("Proc_RpcMigCommand: called from host %d with invalid input buffer size (%d instead of %d).\n",
  1053.            hostID, storagePtr->requestParamSize, sizeof(ProcMigCmd));
  1054.     }
  1055.     status = GEN_INVALID_ARG;
  1056.     goto done;
  1057.     }
  1058.     
  1059.     if (commandPtr->remotePid != (Proc_PID) NIL) {
  1060.     PROC_GET_VALID_PCB(commandPtr->remotePid, procPtr);
  1061.     if (procPtr == (Proc_ControlBlock *) NIL) {
  1062.         if (proc_MigDebugLevel > 3) {
  1063.         panic("Proc_RpcMigCommand: Invalid pid: %x.\n", commandPtr->remotePid);
  1064.         }
  1065.         status = PROC_NO_PEER;
  1066.         goto done;
  1067.     }
  1068.     } else {
  1069.     procPtr = (Proc_ControlBlock *) NIL;
  1070.     }
  1071.  
  1072.     if (commandPtr->command >= PROC_MIGRATE_CMD_NUM_TYPES ||
  1073.     commandPtr->command < 0) {
  1074.     if (proc_MigDebugLevel > 0) {
  1075.         printf("Proc_RpcMigCommand: invalid command number: %d.\n",
  1076.            commandPtr->command);
  1077.     }
  1078.     status = GEN_INVALID_ARG;
  1079.     goto done;
  1080.     }
  1081.     requestSize = storagePtr->requestDataSize;
  1082.     /*
  1083.      * Normally we just pass the buffer as it's given to us, but
  1084.      * it might be a piece of a larger buffer that we malloc and free.
  1085.      * In that case, do some sanity checking and then copy in the buffer.
  1086.      */
  1087.     if (commandPtr->totalSize == requestSize) {
  1088.     inBuf.size = requestSize;
  1089.     inBuf.ptr = storagePtr->requestDataPtr;
  1090.     } else {
  1091.     if (procPtr == (Proc_ControlBlock *) NIL) {
  1092.         if (proc_MigDebugLevel > 0) {
  1093.         printf("Proc_RpcMigCommand: partial buffer not allowed before process set up.\n");
  1094.         status = PROC_NO_PEER;
  1095.         goto done;
  1096.         }
  1097.     }
  1098.     if (commandPtr->offset == 0) {
  1099.         if (procPtr->migCmdBuffer != (Address) NIL) {
  1100.         if (proc_MigDebugLevel > 0) {
  1101.             printf("Proc_RpcMigCommand: buffer already established for process %x.\n",
  1102.                procPtr->processID);
  1103.         }
  1104.         free(procPtr->migCmdBuffer);
  1105.         }
  1106.         procPtr->migCmdBuffer = malloc(commandPtr->totalSize);
  1107.         procPtr->migCmdBufSize = commandPtr->totalSize;
  1108.     } else {
  1109.         if (procPtr->migCmdBuffer == (Address) NIL) {
  1110.         if (proc_MigDebugLevel > 0) {
  1111.             printf("Proc_RpcMigCommand: no buffer established for process %x.\n",
  1112.                procPtr->processID);
  1113.         }
  1114.         status = GEN_INVALID_ARG;
  1115.         goto done;
  1116.         }
  1117.         if (commandPtr->totalSize != procPtr->migCmdBufSize ||
  1118.         commandPtr->offset + requestSize > commandPtr->totalSize) {
  1119.         if (proc_MigDebugLevel > 0) {
  1120.             printf("Proc_RpcMigCommand: mismatch in buffer size for process %x.\n",
  1121.                procPtr->processID);
  1122.         }
  1123.         status = GEN_INVALID_ARG;
  1124.         goto done;
  1125.         }
  1126.     }
  1127.     bcopy(storagePtr->requestDataPtr,
  1128.           procPtr->migCmdBuffer + commandPtr->offset,
  1129.           requestSize);
  1130.     if (commandPtr->offset + requestSize < commandPtr->totalSize) {
  1131.         status = SUCCESS;
  1132.         goto done;
  1133.     }
  1134.     inBuf.size = commandPtr->totalSize;
  1135.     inBuf.ptr = procPtr->migCmdBuffer;
  1136.     }
  1137.     
  1138.     outBuf.size = 0;
  1139.     outBuf.ptr = (Address) NIL;
  1140.  
  1141.     status = (*commandCallbacks[commandPtr->command])
  1142.     (commandPtr, procPtr, &inBuf, &outBuf);
  1143. #ifdef lint
  1144.     status = ProcMigAcceptMigration(commandPtr, procPtr, &inBuf, &outBuf);
  1145.     status = ProcMigReceiveProcess(commandPtr, procPtr, &inBuf, &outBuf);
  1146.     status = ProcMigUpdateState(commandPtr, procPtr, &inBuf, &outBuf);
  1147.     status = ProcMigEncapCallback(commandPtr, procPtr, &inBuf, &outBuf);
  1148.     status = ProcMigDestroyCmd(commandPtr, procPtr, &inBuf, &outBuf);
  1149. #endif /* lint */
  1150.     /*
  1151.      * Free the malloc'ed buffer if it exists.
  1152.      */
  1153.     if ((procPtr != (Proc_ControlBlock *) NIL) &&
  1154.     (procPtr->migCmdBuffer != (Address) NIL)) {
  1155.     free(procPtr->migCmdBuffer);
  1156.     procPtr->migCmdBuffer = (Address) NIL;
  1157.     }
  1158.     if (status == SUCCESS && outBuf.size > 0) {
  1159.     storagePtr->replyDataPtr = outBuf.ptr;
  1160.     storagePtr->replyDataSize = outBuf.size;
  1161.  
  1162.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1163.     replyMemPtr->paramPtr = (Address) NIL;
  1164.     replyMemPtr->dataPtr = outBuf.ptr;
  1165.     if (proc_MigDebugLevel > 5) {
  1166.         printf("Proc_RpcMigCommand: returning status %x.\n", status);
  1167.     }
  1168.     Rpc_Reply(srvToken, SUCCESS, storagePtr, Rpc_FreeMem,
  1169.         (ClientData) replyMemPtr);
  1170.     } else {
  1171. done:
  1172.     if (proc_MigDebugLevel > 2) {
  1173.         printf("Proc_RpcMigCommand: returning status %x.\n", status);
  1174.     }
  1175.     Rpc_Reply(srvToken, status,
  1176.           storagePtr, (int(*)()) NIL, (ClientData) NIL);
  1177.     }
  1178.     return(SUCCESS);
  1179. }
  1180.  
  1181.  
  1182. /*
  1183.  *----------------------------------------------------------------------
  1184.  *
  1185.  * Proc_RpcRemoteCall --
  1186.  *
  1187.  *    Handle a system call for a migrated process.
  1188.  *
  1189.  *    Note: now that this has been moved into the proc module, it
  1190.  *    can be collapsed into the routine it calls....
  1191.  *
  1192.  * Results:
  1193.  *    A return status.
  1194.  *
  1195.  * Side effects:
  1196.  *    None.
  1197.  *
  1198.  *----------------------------------------------------------------------
  1199.  */
  1200. /*ARGSUSED*/
  1201. ReturnStatus
  1202. Proc_RpcRemoteCall(srvToken, clientID, command, storagePtr)
  1203.     ClientData srvToken;    /* Handle on server process passed to
  1204.                  * Rpc_Reply */
  1205.     int clientID;        /* Sprite ID of client host */
  1206.     int command;        /* Command identifier */
  1207.     Rpc_Storage *storagePtr;    /* The request fields refer to the request
  1208.                  * buffers and also indicate the exact amount
  1209.                  * of data in the request buffers.  The reply
  1210.                  * fields are initialized to NIL for the
  1211.                  * pointers and 0 for the lengths.  This can
  1212.                  * be passed to Rpc_Reply */
  1213. {
  1214.     Rpc_ReplyMem    *replyMemPtr;
  1215.     Address returnData = (Address) NIL;
  1216.     int returnDataLength = 0;
  1217.     ReturnStatus status;
  1218.  
  1219.     status = RpcRemoteCall((Proc_RemoteCall *)storagePtr->requestParamPtr,
  1220.          storagePtr->requestDataPtr, storagePtr->requestDataSize,
  1221.          &returnData, &returnDataLength);
  1222.  
  1223.     storagePtr->replyDataPtr = returnData;
  1224.     storagePtr->replyDataSize = returnDataLength;
  1225.  
  1226.     replyMemPtr = (Rpc_ReplyMem *) malloc(sizeof(Rpc_ReplyMem));
  1227.     replyMemPtr->paramPtr = (Address) NIL;
  1228.     replyMemPtr->dataPtr = returnData;
  1229.     Rpc_Reply(srvToken, status, storagePtr, Rpc_FreeMem,
  1230.         (ClientData) replyMemPtr);
  1231.  
  1232.     return(status);
  1233. }
  1234.